/*
 * Copyright 2002-2025 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.support;

import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.core.SimpleAliasRegistry;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

/**
 * Generic registry for shared bean instances, implementing the
 * {@link org.springframework.beans.factory.config.SingletonBeanRegistry}.
 * Allows for registering singleton instances that should be shared
 * for all callers of the registry, to be obtained via bean name.
 *
 * <p>Also supports registration of
 * {@link org.springframework.beans.factory.DisposableBean} instances,
 * (which might or might not correspond to registered singletons),
 * to be destroyed on shutdown of the registry. Dependencies between
 * beans can be registered to enforce an appropriate shutdown order.
 *
 * <p>This class mainly serves as base class for
 * {@link org.springframework.beans.factory.BeanFactory} implementations,
 * factoring out the common management of singleton bean instances. Note that
 * the {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
 * interface extends the {@link SingletonBeanRegistry} interface.
 *
 * <p>Note that this class assumes neither a bean definition concept
 * nor a specific creation process for bean instances, in contrast to
 * {@link AbstractBeanFactory} and {@link DefaultListableBeanFactory}
 * (which inherit from it). Can alternatively also be used as a nested
 * helper to delegate to.
 *
 * @author Juergen Hoeller
 * @since 2.0
 * @see #registerSingleton
 * @see #registerDisposableBean
 * @see org.springframework.beans.factory.DisposableBean
 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory
 */
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** Maximum number of suppressed exceptions to preserve. */
	private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;


	/**
	 * 创建单例实例的锁
	 *
	 * Common lock for singleton creation.
	 *  */
	final Lock singletonLock = new ReentrantLock();

	/**
	 * 缓存的单例 bean 相关信息 这就是一级缓存
	 * key 为 bean name，value 为 bean 实例信息(已经初始化好了)
	 *
	 * Cache of singleton objects: bean name to bean instance.
	 * */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/**
	 * 缓存的 bean 的 工厂对象，这就是三级缓存
	 * 此时 value 缓存的是一个  lambda 表达式，注释中有说明为什么存储的是一个表达式的原因
	 *
	 *  1. singletonFactories map 、registeredSingletons set 中保存值，即在三级缓存的 第三级 map 中存储值，注意:value 	为一个 lambda 表达式，需要回调异步执行
	 *  2. 循环依赖 x,y,在y填充x 的时候，在三级缓存中会进入到  {@link AbstractAutowireCapableBeanFactory#getEarlyBeanReference(String, RootBeanDefinition, Object)} 方法，该方法可以看下
	 *  3.如果 x 和 y 循环依赖，且在 y 的 afterPropertiesSet 方法中有调用 x 中的方法情况下(假如 x 是有代理需求)，如果存储的是 半成品 bean,此时 y 就不能成功调用 x 中生成的代理方法，
	 *  这就有问题了，所以这里存储的是一个 表达式，用于实现提前将 x 的 Aware 接口功能 实现 --- 查看 getEarlyBeanReference 方法实现
	 *
	 * Creation-time registry of singleton factories: bean name to ObjectFactory.
	 * */
	private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>(16);

	/** Custom callbacks for singleton creation/registration. */
	private final Map<String, Consumer<Object>> singletonCallbacks = new ConcurrentHashMap<>(16);

	/**
	 *  缓存中的 bean 实例早期对象，此时的 value 是半成品 bean，即已经实例化但未初始化完成
	 *  即二级缓存
	 *
	 *  Cache of early singleton objects: bean name to bean instance.
	 *  */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

	/**
	 * 缓存已经实例化的 单例 bean，此时还未进行初始化操作
	 *
	 * Set of registered singletons, containing the bean names in registration order.
	 * */
	private final Set<String> registeredSingletons = Collections.synchronizedSet(new LinkedHashSet<>(256));

	/**
	 * 所有正在被创建的单例  bean
	 * 为什么要用 Set 来存储呢，spring 明明是一个一个 bean 按照字母顺序来实例化的
	 *  	这就是因为有循环依赖的存在，由于循环依赖的存在 需要被依赖的 bean 也进行创建并返回内存地址后，依赖方才能实例化结束，所以这里才有存储多个正在创建中的 bean 的必要性
	 *
	 *
	 * Names of beans that are currently in creation.
	 * */
	private final Set<String> singletonsCurrentlyInCreation = ConcurrentHashMap.newKeySet(16);

	/**
	 * 当前正在创建中的 bean 缓存信息，包括单例、原型 bean 等情况
	 *
	 * Names of beans currently excluded from in creation checks.
	 * */
	private final Set<String> inCreationCheckExclusions = ConcurrentHashMap.newKeySet(16);

	/** Specific lock for lenient creation tracking. */
	private final Lock lenientCreationLock = new ReentrantLock();

	/** Specific lock condition for lenient creation tracking. */
	private final Condition lenientCreationFinished = this.lenientCreationLock.newCondition();

	/** Names of beans that are currently in lenient creation. */
	private final Set<String> singletonsInLenientCreation = new HashSet<>();

	/** Flag that indicates whether we're currently within destroySingletons. */
	private volatile boolean singletonsCurrentlyInDestruction = false;

	/** Collection of suppressed Exceptions, available for associating related causes. */
	@Nullable
	private Set<Exception> suppressedExceptions;

	/**
	 *
	 * 一次性bean实例：bean名称到一次性实例。
	 *
	 * Disposable bean instances: bean name to disposable instance.
	 * */
	private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();

	/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

	/**
	 * 保存依赖注入，
	 * key 为 bean name
	 * value 为 写有 @Resouece 注解的所在类的 bean name
	 *
	 * Map between dependent bean names: bean name to Set of dependent bean names.
	 * */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	/**
	 * 在依赖的 bean 名称之间建立映射关系：将一个 bean 的名称映射到该 bean 所依赖的 bean 名称的集合。
	 *  key为： 写有 @Resouece 注解的所在类的 bean name
	 *  value为： 依赖注入的 bean name 数组
	 *
	 * Map between depending bean names: bean name to Set of bean names for the bean's dependencies.
	 * */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);


	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		this.singletonLock.lock();
		try {
			addSingleton(beanName, singletonObject);
		}
		finally {
			this.singletonLock.unlock();
		}
	}

	/**
	 * 将给定的单例对象添加到该工厂的单例缓存中
	 * 需要关注：在循环依赖的时候调用
	 *
	 * Add the given singleton object to the singleton registry.
	 * <p>To be called for exposure of freshly registered/created singletons.
	 * @param beanName the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {

		Object oldObject = this.singletonObjects.putIfAbsent(beanName, singletonObject);
		if (oldObject != null) {
			throw new IllegalStateException("Could not register object [" + singletonObject +
					"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
		}

		// 删除 三级缓存
		this.singletonFactories.remove(beanName);

		// 删除 二级缓存
		this.earlySingletonObjects.remove(beanName);

		// 添加 一级缓存单例对象
		this.registeredSingletons.add(beanName);

		Consumer<Object> callback = this.singletonCallbacks.get(beanName);
		if (callback != null) {
			callback.accept(singletonObject);
		}
	}

	/**
	 * 将实例化的bean 信息添加到 三级缓存中
	 * 缓存已经实例化的 单例 bean，此时还未进行初始化操作
	 *
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 * <p>To be called for early exposure purposes, for example, to be able to
	 * resolve circular references.
	 * @param beanName the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");

		//  将实例化的bean 信息添加到 三级缓存中，此时 value 是一个 lambda 对象
		this.singletonFactories.put(beanName, singletonFactory);

		this.earlySingletonObjects.remove(beanName);

		// 缓存已经实例化的 单例 bean，此时还未进行初始化操作
		this.registeredSingletons.add(beanName);
	}

	@Override
	public void addSingletonCallback(String beanName, Consumer<Object> singletonConsumer) {
		this.singletonCallbacks.put(beanName, singletonConsumer);
	}

	/**
	 * 从单例池中获得 bean 相关的信息
	 *
	 * @param beanName the name of the bean to look for
	 * @return
	 */
	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

	/**
	 * 从单例池中获得 bean 相关的信息
	 *
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for									bean 的名称
	 * @param allowEarlyReference whether early references should be created or not     true 为允许返回早期对象
	 * @return the registered singleton object, or {@code null} if none found
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		/**
		 * 从单例池中根据 bean 名称获得 bean 实例相关信息 ，即从一级缓存中获得 bean 实例相关信息
		 *
		 * Quick check for existing instance without full singleton lock.
		 */
		Object singletonObject = this.singletonObjects.get(beanName);

		// 一级缓存中此时没有 且 当前 bean 此时正在在创建  beanName Set 中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

			/**
			 * 这个 if 什么时候会进呢？
			 *  x 依赖 y,y 也依赖 x, 按照 bean Name 的顺序进行初始化
			 *  1.x 先创建，当x 进入到 属性填充的时候会初始化 y，此时 x 已经把值缓存到了 正在创建中的 beanName Set 中，即 singletonsCurrentlyInCreation Set 中有值了
			 *  2.当 y 创建过程中，会初始化 x,此时 调用 x 的 doGetBean 方法，会发现 x 已经是正在创建中了，此时就会进入这个 if
			 *
			 *  也就是说   只有循环依赖的时候    后创建的 bean 在属性填充 先创建的 bean 的时候，才会进入这个 if
			 *
			 *  为了方便理解这三级缓存，需要把创建 x 中使用到的 缓存 map 画出来，这样一看就知道了  singletonFactories 是什么时候填充的值
			 */


			/**
			 * 一级缓存中没有对应的实例信息，那么此时 从二级缓存中去获得
			 */
			singletonObject = this.earlySingletonObjects.get(beanName);

			if (singletonObject == null && allowEarlyReference) {

				// 二级缓存中也没有，那么此时就进入到创建对象的步骤

				/**
				 * 先去获得创建单例实例的锁，即此时才进行获取锁的操作
				 */
				if (!this.singletonLock.tryLock()) {
					// Avoid early singleton inference outside of original creation thread.
					return null;
				}

				/**
				 * 下面步骤为获得锁成功后，进行创建实例对象的过程
				 */


				try {
					/**
					 * 下面进行双重检验锁操作
					 *
					 * Consistent creation of early reference within full singleton lock.
					 */
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {

						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {

							/**
							 * 此时从三级缓存中去获取
							 *
							 *  这是一个 lambda 表达式，是需要异步执行的，用于实现扩展功能，因为在循环依赖的时候，可能注入的是一个代理后的对象，不能是一个半成品对象，这样就灵活多了
							 *
							 */
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

							if (singletonFactory != null) {
								/**
								 * singletonFactory.getObject() 会回调到 lambda 表达式里面去 ，即  {@link AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])}
								 * 此时返回的是半成品 bean, 即 已经实例化但还未初始化完成
								 *
								 * 问题：
								 * 1.singletonFactories 中为什么不直接缓存半成品 bean,而是要存储一个 lambda  表达式
								 * 	答 如果 x 和 y 循环依赖，且在 y 的 afterPropertiesSet 方法中有调用 x 中的方法情况下(假如 x 是有代理需求)，
								 * 	如果存储的是 半成品 bean,此时 y 就不能成功调用 x 中生成的代理方法，这就有问题了，所以这里存储的是一个 表达式，用于实现提前将 x 的 Aware 接口功能 实现
								 */
								singletonObject = singletonFactory.getObject();


								/**
								 * 将 半成品的 bean 放入到 二级缓存中, 同时从三级缓存中移除 lambda 表达式 对象
								 *
								 *
								 * 	通过代码也知道其实两级缓存也能解决循环依赖
								 *
								 * 从源码上看三级缓存存的是ObjectFactory（lambda表达式）也就是bean未实例化（代理类未实例化实际的类以及通过反射实例化，
								 * lambda是封装了遍历后置处理器可以进一步加工，代理类生成也就是这个时候）其实直接在产生ObjectFactory这步直接执行后   放入二级缓存中也是可以  的，
								 * 但从性能分析如果没有循环引用这个二级缓存也不会被用到，最终在doCreateBean→initializeBean→applyBeanPostProcessorsAfterInitialization
								 * 也有一段代码产生包装类的代码和三级缓存中的ObjectFactory是一样的都是遍历后缀处理器处理，
								 * 	而代理处理类（想要验证需要开启AOP不然不会有该处理类）是一样的(org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator实现类
								 * 是org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator)所调用的方法内容是差不多的逻辑是等价的
								 *
								 * 而之所以采用 三级缓存是因为
								 * 	1.为了延迟初始化而设计三级缓存。减少非循环依赖时无需初始化三级缓存的 ObjectFactory,从而减少性能开销和内存占用；
								 * 	2.还有另一个原因是后置处理器目的是在初始化后再执行这是Spring的设计原则(生命周期);
								 *
								 * Singleton could have been added or removed in the meantime.
								 */
								if (this.singletonFactories.remove(beanName) != null) {
									this.earlySingletonObjects.put(beanName, singletonObject);
								}
								else {
									singletonObject = this.singletonObjects.get(beanName);
								}
							}
						}
					}
				}
				finally {
					this.singletonLock.unlock();
				}
			}
		}
		return singletonObject;
	}

	/**
	 * 该方法用于获得当前 beanName 对应的 实例化 bean 信息
	 *
	 * 循环依赖,x和y,当 y 完成了 属性 x 的循环依赖填充的时候，会进入这个方法 完成y 的实例化，并清除 x 在三级缓存中的值
	 *
	 * Return the (raw) singleton object registered under the given name,
	 * creating and registering a new one if none registered yet.
	 * @param beanName the name of the bean
	 * @param singletonFactory the ObjectFactory to lazily create the singleton
	 * with, if necessary
	 * @return the registered singleton object
	 */
	@SuppressWarnings("NullAway")
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");

		// 获得锁操作
		Boolean lockFlag = isCurrentThreadAllowedToHoldSingletonLock();
		boolean acquireLock = !Boolean.FALSE.equals(lockFlag);
		boolean locked = (acquireLock && this.singletonLock.tryLock());
		try {

			/**
			 * 从一级缓存中判断当前 beanName 对应的 bean 是否已经实例化且初始化完毕了
			 */
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {

				/**
				 * 获得锁成功，那么就开始进行处理，一般情况 不会进入该方法中
				 * 注意 默认情况下 不会进入该方法  不会！！！！！
				 */
				if (acquireLock && !locked) {

					if (Boolean.TRUE.equals(lockFlag)) {
						// Another thread is busy in a singleton factory callback, potentially blocked.
						// Fallback as of 6.2: process given singleton bean outside of singleton lock.
						// Thread-safe exposure is still guaranteed, there is just a risk of collisions
						// when triggering creation of other beans as dependencies of the current bean.
						if (logger.isInfoEnabled()) {
							logger.info("Creating singleton bean '" + beanName + "' in thread \"" +
									Thread.currentThread().getName() + "\" while other thread holds " +
									"singleton lock for other beans " + this.singletonsCurrentlyInCreation);
						}
						this.lenientCreationLock.lock();
						try {
							this.singletonsInLenientCreation.add(beanName);
						}
						finally {
							this.lenientCreationLock.unlock();
						}
					}
					else {
						// No specific locking indication (outside a coordinated bootstrap) and
						// singleton lock currently held by some other creation method -> wait.
						this.singletonLock.lock();
						locked = true;
						// Singleton object might have possibly appeared in the meantime.
						singletonObject = this.singletonObjects.get(beanName);
						if (singletonObject != null) {
							return singletonObject;
						}
					}
				}

				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}

				try {
					/**
					 * 尝试将当前 beanName 添加到正在创建中的  beanName Set 中，如果能添加成功，则方法继续往下走，否则就抛出异常
					 */
					beforeSingletonCreation(beanName);
				}
				catch (BeanCurrentlyInCreationException ex) {
					this.lenientCreationLock.lock();
					try {
						while ((singletonObject = this.singletonObjects.get(beanName)) == null) {
							if (!this.singletonsInLenientCreation.contains(beanName)) {
								break;
							}
							try {
								this.lenientCreationFinished.await();
							}
							catch (InterruptedException ie) {
								Thread.currentThread().interrupt();
							}
						}
					}
					finally {
						this.lenientCreationLock.unlock();
					}
					if (singletonObject != null) {
						return singletonObject;
					}
					if (locked) {
						throw ex;
					}
					// Try late locking for waiting on specific bean to be finished.
					this.singletonLock.lock();
					locked = true;
					// Lock-created singleton object should have appeared in the meantime.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject != null) {
						return singletonObject;
					}
					beforeSingletonCreation(beanName);
				}

				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (locked && this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}


				try {
					/**
					 * 再次从单例池中进行判断
					 *
					 * Leniently created singleton object could have appeared in the meantime.
					 */
					singletonObject = this.singletonObjects.get(beanName);


					if (singletonObject == null) {
						/**
						 * 开始创建 这里会回到 lamaba 表达式中
						 * 根据 beanName 和 RootBeanDefinition 实例化 bean
						 *
						 * 在 doCreateBean 方法中的 属性填充步骤 做了，依赖注入的处理！！！
						 *
						 * 即 {@link AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])}
						 *
						 */
						singletonObject = singletonFactory.getObject();
						newSingleton = true;
					}
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}

				/**
				 * 单例 bean 创建完毕后，将 bean 添加到一级缓存 即 registeredSingletons 中
				 * 并同时删除 二级缓存、三级缓存中的信息
				 */
				if (newSingleton) {
					try {
						/**
						 * 将给定的单例对象添加到该工厂的单例缓存中 并 二级缓存、三级缓存中的信息
						 */
						addSingleton(beanName, singletonObject);
					}
					catch (IllegalStateException ex) {
						// Leniently accept same instance if implicitly appeared.
						Object object = this.singletonObjects.get(beanName);
						if (singletonObject != object) {
							throw ex;
						}
					}
				}

			}
			return singletonObject;
		}
		finally {
			if (locked) {
				this.singletonLock.unlock();
			}
			this.lenientCreationLock.lock();
			try {
				this.singletonsInLenientCreation.remove(beanName);
				this.lenientCreationFinished.signalAll();
			}
			finally {
				this.lenientCreationLock.unlock();
			}
		}
	}

	/**
	 * Determine whether the current thread is allowed to hold the singleton lock.
	 * <p>By default, any thread may acquire and hold the singleton lock, except
	 * background threads from {@link DefaultListableBeanFactory#setBootstrapExecutor}.
	 * @return {@code false} if the current thread is explicitly not allowed to hold
	 * the lock, {@code true} if it is explicitly allowed to hold the lock but also
	 * accepts lenient fallback behavior, or {@code null} if there is no specific
	 * indication (traditional behavior: always holding a full lock)
	 * @since 6.2
	 */
	@Nullable
	protected Boolean isCurrentThreadAllowedToHoldSingletonLock() {
		return null;
	}

	/**
	 * Register an exception that happened to get suppressed during the creation of a
	 * singleton bean instance, for example, a temporary circular reference resolution problem.
	 * <p>The default implementation preserves any given exception in this registry's
	 * collection of suppressed exceptions, up to a limit of 100 exceptions, adding
	 * them as related causes to an eventual top-level {@link BeanCreationException}.
	 * @param ex the Exception to register
	 * @see BeanCreationException#getRelatedCauses()
	 */
	protected void onSuppressedException(Exception ex) {
		if (this.suppressedExceptions != null && this.suppressedExceptions.size() < SUPPRESSED_EXCEPTIONS_LIMIT) {
			this.suppressedExceptions.add(ex);
		}
	}

	/**
	 * Remove the bean with the given name from the singleton registry, either on
	 * regular destruction or on cleanup after early exposure when creation failed.
	 * @param beanName the name of the bean
	 */
	protected void removeSingleton(String beanName) {
		this.singletonObjects.remove(beanName);
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.remove(beanName);
	}

	@Override
	public boolean containsSingleton(String beanName) {
		return this.singletonObjects.containsKey(beanName);
	}

	@Override
	public String[] getSingletonNames() {
		return StringUtils.toStringArray(this.registeredSingletons);
	}

	@Override
	public int getSingletonCount() {
		return this.registeredSingletons.size();
	}


	public void setCurrentlyInCreation(String beanName, boolean inCreation) {
		Assert.notNull(beanName, "Bean name must not be null");
		if (!inCreation) {
			this.inCreationCheckExclusions.add(beanName);
		}
		else {
			this.inCreationCheckExclusions.remove(beanName);
		}
	}

	public boolean isCurrentlyInCreation(String beanName) {
		Assert.notNull(beanName, "Bean name must not be null");
		return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
	}

	protected boolean isActuallyInCreation(String beanName) {
		return isSingletonCurrentlyInCreation(beanName);
	}

	/**
	 * 所有正在被创建的  bean
	 *
	 * Return whether the specified singleton bean is currently in creation
	 * (within the entire factory).
	 * @param beanName the name of the bean
	 */
	public boolean isSingletonCurrentlyInCreation(@Nullable String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

	/**
	 * Callback before singleton creation.
	 * <p>The default implementation register the singleton as currently in creation.
	 * @param beanName the name of the singleton about to be created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

	/**
	 * Callback after singleton creation.
	 * <p>The default implementation marks the singleton as not in creation anymore.
	 * @param beanName the name of the singleton that has been created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}


	/**
	 * 注册 bean
	 *
	 * Add the given bean to the list of disposable beans in this registry.
	 * <p>Disposable beans usually correspond to registered singletons,
	 * matching the bean name but potentially being a different instance
	 * (for example, a DisposableBean adapter for a singleton that does not
	 * naturally implement Spring's DisposableBean interface).
	 * @param beanName the name of the bean
	 * @param bean the bean instance
	 */
	public void registerDisposableBean(String beanName, DisposableBean bean) {
		// 将 初始化完毕的单例 bean 进行注册
		synchronized (this.disposableBeans) {
			this.disposableBeans.put(beanName, bean);
		}
	}

	/**
	 * Register a containment relationship between two beans,
	 * for example, between an inner bean and its containing outer bean.
	 * <p>Also registers the containing bean as dependent on the contained bean
	 * in terms of destruction order.
	 * @param containedBeanName the name of the contained (inner) bean
	 * @param containingBeanName the name of the containing (outer) bean
	 * @see #registerDependentBean
	 */
	public void registerContainedBean(String containedBeanName, String containingBeanName) {
		synchronized (this.containedBeanMap) {
			Set<String> containedBeans =
					this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
			if (!containedBeans.add(containedBeanName)) {
				return;
			}
		}
		registerDependentBean(containedBeanName, containingBeanName);
	}

	/**
	 * 将给定的 bean 对象进行注入
	 *
	 * Register a dependent bean for the given bean,
	 * to be destroyed before the given bean is destroyed.
	 * @param beanName the name of the bean
	 * @param dependentBeanName the name of the dependent bean 依赖项 bean 的名称
	 */
	public void registerDependentBean(String beanName, String dependentBeanName) {

		// 获得注册的 bean name
		String canonicalName = canonicalName(beanName);

		synchronized (this.dependentBeanMap) {
			Set<String> dependentBeans =
					this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));

			// 将 依赖项 bean 的名称 添加到缓存中
			if (!dependentBeans.add(dependentBeanName)) {
				return;
			}
		}

		/**
		 * 在依赖的 bean 名称之间建立映射关系：将一个 bean 的名称映射到该 bean 所依赖的 bean 名称的集合。
		 */
		synchronized (this.dependenciesForBeanMap) {
			Set<String> dependenciesForBean =
					this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));

			dependenciesForBean.add(canonicalName);
		}
	}

	/**
	 * Determine whether the specified dependent bean has been registered as
	 * dependent on the given bean or on any of its transitive dependencies.
	 * @param beanName the name of the bean to check
	 * @param dependentBeanName the name of the dependent bean
	 * @since 4.0
	 */
	protected boolean isDependent(String beanName, String dependentBeanName) {
		synchronized (this.dependentBeanMap) {
			return isDependent(beanName, dependentBeanName, null);
		}
	}

	private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
		if (alreadySeen != null && alreadySeen.contains(beanName)) {
			return false;
		}
		String canonicalName = canonicalName(beanName);
		Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
		if (dependentBeans == null || dependentBeans.isEmpty()) {
			return false;
		}
		if (dependentBeans.contains(dependentBeanName)) {
			return true;
		}
		if (alreadySeen == null) {
			alreadySeen = new HashSet<>();
		}
		alreadySeen.add(beanName);
		for (String transitiveDependency : dependentBeans) {
			if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Determine whether a dependent bean has been registered for the given name.
	 * @param beanName the name of the bean to check
	 */
	protected boolean hasDependentBean(String beanName) {
		return this.dependentBeanMap.containsKey(beanName);
	}

	/**
	 * Return the names of all beans which depend on the specified bean, if any.
	 * @param beanName the name of the bean
	 * @return the array of dependent bean names, or an empty array if none
	 */
	public String[] getDependentBeans(String beanName) {
		Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
		if (dependentBeans == null) {
			return new String[0];
		}
		synchronized (this.dependentBeanMap) {
			return StringUtils.toStringArray(dependentBeans);
		}
	}

	/**
	 * Return the names of all beans that the specified bean depends on, if any.
	 * @param beanName the name of the bean
	 * @return the array of names of beans which the bean depends on,
	 * or an empty array if none
	 */
	public String[] getDependenciesForBean(String beanName) {
		Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
		if (dependenciesForBean == null) {
			return new String[0];
		}
		synchronized (this.dependenciesForBeanMap) {
			return StringUtils.toStringArray(dependenciesForBean);
		}
	}

	public void destroySingletons() {
		if (logger.isTraceEnabled()) {
			logger.trace("Destroying singletons in " + this);
		}
		this.singletonsCurrentlyInDestruction = true;

		String[] disposableBeanNames;
		synchronized (this.disposableBeans) {
			disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
		}
		for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
			destroySingleton(disposableBeanNames[i]);
		}

		this.containedBeanMap.clear();
		this.dependentBeanMap.clear();
		this.dependenciesForBeanMap.clear();

		this.singletonLock.lock();
		try {
			clearSingletonCache();
		}
		finally {
			this.singletonLock.unlock();
		}
	}

	/**
	 * Clear all cached singleton instances in this registry.
	 * @since 4.3.15
	 */
	protected void clearSingletonCache() {
		this.singletonObjects.clear();
		this.singletonFactories.clear();
		this.earlySingletonObjects.clear();
		this.registeredSingletons.clear();
		this.singletonsCurrentlyInDestruction = false;
	}

	/**
	 * Destroy the given bean. Delegates to {@code destroyBean}
	 * if a corresponding disposable bean instance is found.
	 * @param beanName the name of the bean
	 * @see #destroyBean
	 */
	public void destroySingleton(String beanName) {
		// Destroy the corresponding DisposableBean instance.
		// This also triggers the destruction of dependent beans.
		DisposableBean disposableBean;
		synchronized (this.disposableBeans) {
			disposableBean = this.disposableBeans.remove(beanName);
		}
		destroyBean(beanName, disposableBean);

		// destroySingletons() removes all singleton instances at the end,
		// leniently tolerating late retrieval during the shutdown phase.
		if (!this.singletonsCurrentlyInDestruction) {
			// For an individual destruction, remove the registered instance now.
			// As of 6.2, this happens after the current bean's destruction step,
			// allowing for late bean retrieval by on-demand suppliers etc.
			this.singletonLock.lock();
			try {
				removeSingleton(beanName);
			}
			finally {
				this.singletonLock.unlock();
			}
		}
	}

	/**
	 * Destroy the given bean. Must destroy beans that depend on the given
	 * bean before the bean itself. Should not throw any exceptions.
	 * @param beanName the name of the bean
	 * @param bean the bean instance to destroy
	 */
	protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
		// Trigger destruction of dependent beans first...
		Set<String> dependentBeanNames;
		synchronized (this.dependentBeanMap) {
			// Within full synchronization in order to guarantee a disconnected Set
			dependentBeanNames = this.dependentBeanMap.remove(beanName);
		}
		if (dependentBeanNames != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependentBeanNames);
			}
			for (String dependentBeanName : dependentBeanNames) {
				destroySingleton(dependentBeanName);
			}
		}

		// Actually destroy the bean now...
		if (bean != null) {
			try {
				bean.destroy();
			}
			catch (Throwable ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
				}
			}
		}

		// Trigger destruction of contained beans...
		Set<String> containedBeans;
		synchronized (this.containedBeanMap) {
			// Within full synchronization in order to guarantee a disconnected Set
			containedBeans = this.containedBeanMap.remove(beanName);
		}
		if (containedBeans != null) {
			for (String containedBeanName : containedBeans) {
				destroySingleton(containedBeanName);
			}
		}

		// Remove destroyed bean from other beans' dependencies.
		synchronized (this.dependentBeanMap) {
			for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
				Map.Entry<String, Set<String>> entry = it.next();
				Set<String> dependenciesToClean = entry.getValue();
				dependenciesToClean.remove(beanName);
				if (dependenciesToClean.isEmpty()) {
					it.remove();
				}
			}
		}

		// Remove destroyed bean's prepared dependency information.
		this.dependenciesForBeanMap.remove(beanName);
	}

	@Deprecated(since = "6.2")
	@Override
	public final Object getSingletonMutex() {
		return new Object();
	}

}
